package com.joint.cloud.auth.config.custom;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;

/**
 * 认证管理
 *
 * @author keets
 * @date 2017/8/5
 */
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Resource(name = "licenseRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    private HashOperations<String, String, Object> hashOperations;

    @PostConstruct
    private void init() {
        hashOperations = redisTemplate.opsForHash();
    }

    private static final String CMP_LICENSE_CHECK = "CMP_ACCESS_CHECK";
    private final static String LICENSE_STATUS = "LICENSE_STATUS";
    private final static String LICENSE_INVALID = "LICENSE_INVALID";

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();

        Map data;
        if (authentication.getDetails() instanceof Map) {
            data = (Map) authentication.getDetails();
        } else {
            return null;
        }
        String clientId = (String) data.get("client");
        Assert.hasText(clientId, "clientId must have value");

        String password = (String) authentication.getCredentials();
        try {
            userDetailsService.loadUserByUsername(username);
        } catch (NoSuchClientException | UsernameNotFoundException e) {
            throw new BadCredentialsException("用户名错误");
        }

        CustomUserDetails customUserDetails = checkUsernameAndPassword(username, password);
        if (customUserDetails == null) {
            throw new BadCredentialsException("用户名或密码错误");
        }

        /**
         * 如果是非超级管理员 && 证书过期，不允许登录
         * 如果是超级管理员 && 证书过期，允许登录，只访问许可证书菜单
         */
        String licenseStatus = this.getCheckStatus(LICENSE_STATUS);
//        if(!StringUtils.hasLength(licenseStatus)){
//            throw new LicenseStatusException("后台服务未启动，请稍后重试");
//        } else if (LICENSE_INVALID.equals(licenseStatus) && !customUserDetails.getRoles().contains("SUPER_ADMIN_ROLE")) {
//            throw new LicenseStatusException("许可证书已过期");
//        }

        customUserDetails.setClientId(clientId);
        return new CustomAuthenticationToken(customUserDetails);
    }

    private CustomUserDetails checkUsernameAndPassword(String username, String password) {
        CustomUserDetails userDetails = (CustomUserDetails) userDetailsService.loadUserByUsername(username);
        if (userDetails == null || !userDetails.getPassword().equals(password)) {
            return null;
        }
        return userDetails;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }

    private String getCheckStatus(String id) {
        return (String) hashOperations.get(CMP_LICENSE_CHECK, id);
    }
}